package com.loe.mvp.ext_app

import android.app.Activity
import androidx.fragment.app.Fragment
import com.loe.mvp.ext_java.boolean
import com.loe.mvp.ext_java.double
import com.loe.mvp.ext_java.int
import com.loe.mvp.ext_java.long
import org.json.JSONArray
import org.json.JSONObject
import java.io.Serializable
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

/***************************************************** intent参数 *****************************************************/

fun Activity.intentStringExtra(key: String, def: String = "") = object : ReadWriteProperty<Activity, String>
{
    private var cacheValue: String? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): String
    {
        if (cacheValue == null)
        {
            cacheValue = intent.getStringExtra(key) ?: def
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: String)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

fun Activity.intentIntExtra(key: String, def: Int = 0) = object : ReadWriteProperty<Activity, Int>
{
    private var cacheValue: Int? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): Int
    {
        if (cacheValue == null)
        {
            cacheValue = intent.getIntExtra(key, def)
            if (cacheValue == def)
            {
                val s = intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.int
                }
            }
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: Int)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

fun Activity.intentLongExtra(key: String, def: Long = 0) = object : ReadWriteProperty<Activity, Long>
{
    private var cacheValue: Long? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): Long
    {
        if (cacheValue == null)
        {
            cacheValue = intent.getLongExtra(key, def)
            if (cacheValue == def)
            {
                val s = intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.long
                }
            }
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: Long)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

fun Activity.intentBooleanExtra(key: String, def: Boolean = false) = object : ReadWriteProperty<Activity, Boolean>
{
    private var cacheValue: Boolean? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): Boolean
    {
        if (cacheValue == null)
        {
            cacheValue = intent.getBooleanExtra(key, def)
            if (cacheValue == def)
            {
                val s = intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.boolean
                }
            }
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: Boolean)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

fun Activity.intentDoubleExtra(key: String, def: Double = 0.0) = object : ReadWriteProperty<Activity, Double>
{
    private var cacheValue: Double? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): Double
    {
        if (cacheValue == null)
        {
            cacheValue = intent.getDoubleExtra(key, def)
            if (cacheValue == def)
            {
                val s = intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.double
                }
            }
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: Double)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

fun Activity.intentJsonOrNullExtra(key: String) = object : ReadWriteProperty<Activity, JSONObject?>
{
    private var cacheValue: JSONObject? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): JSONObject?
    {
        if (cacheValue == null)
        {
            val extra = intent.getStringExtra(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = JSONObject(extra)
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: JSONObject?)
    {
        cacheValue = value
        intent.putExtra(key, value.toString())
    }
}

fun Activity.intentJsonExtra(key: String) = object : ReadWriteProperty<Activity, JSONObject>
{
    private var cacheValue: JSONObject? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): JSONObject
    {
        if (cacheValue == null) cacheValue = try
        {
            JSONObject(intent.getStringExtra(key))
        } catch (e: Exception)
        {
            JSONObject()
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: JSONObject)
    {
        cacheValue = value
        intent.putExtra(key, value.toString())
    }
}

fun Activity.intentJsonArrayOrNullExtra(key: String) = object : ReadWriteProperty<Activity, JSONArray?>
{
    private var cacheValue: JSONArray? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): JSONArray?
    {
        if (cacheValue == null)
        {
            val extra = intent.getStringExtra(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = JSONArray(extra)
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: JSONArray?)
    {
        cacheValue = value
        intent.putExtra(key, value.toString())
    }
}

fun Activity.intentJsonArrayExtra(key: String) = object : ReadWriteProperty<Activity, JSONArray>
{
    private var cacheValue: JSONArray? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): JSONArray
    {
        if (cacheValue == null) cacheValue = try
        {
            JSONArray(intent.getStringExtra(key))
        } catch (e: Exception)
        {
            JSONArray()
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: JSONArray)
    {
        cacheValue = value
        intent.putExtra(key, value.toString())
    }
}

fun <T : Serializable> Activity.intentSerializableExtra(key: String) = object : ReadWriteProperty<Activity, T?>
{
    private var cacheValue: T? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): T?
    {
        if (cacheValue == null)
        {
            val extra = intent.getSerializableExtra(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = extra as T
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: T?)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

fun <T : Serializable> Activity.intentSerializableSafeExtra(key: String) = object : ReadWriteProperty<Activity, T>
{
    private var cacheValue: T? = null

    override fun getValue(thisRef: Activity, property: KProperty<*>): T
    {
        if (cacheValue == null)
        {
            cacheValue = intent.getSerializableExtra(key) as T
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Activity, property: KProperty<*>, value: T)
    {
        cacheValue = value
        intent.putExtra(key, value)
    }
}

/********************************************************** frag intent ****************************************************/

fun Fragment.intentIntExtra(key: String, def: Int = 0) = object : ReadWriteProperty<Fragment, Int>
{
    private var cacheValue: Int? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Int
    {
        if (activity != null && cacheValue == null)
        {
            cacheValue = activity!!.intent.getIntExtra(key, def)
            if (cacheValue == def)
            {
                val s = activity!!.intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.int
                }
            }
        }
        return cacheValue ?: def
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Int)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value)
    }
}

fun Fragment.intentStringExtra(key: String, def: String = "") = object : ReadWriteProperty<Fragment, String>
{
    private var cacheValue: String? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): String
    {
        if (activity != null && cacheValue == null)
        {
            cacheValue = activity!!.intent.getStringExtra(key) ?: def
        }
        return cacheValue ?: def
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: String)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value)
    }
}

fun Fragment.intentLongExtra(key: String, def: Long = 0) = object : ReadWriteProperty<Fragment, Long>
{
    private var cacheValue: Long? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Long
    {
        if (activity != null && cacheValue == null)
        {
            cacheValue = activity!!.intent.getLongExtra(key, def)
            if (cacheValue == def)
            {
                val s = activity!!.intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.long
                }
            }
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Long)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value)
    }
}

fun Fragment.intentBooleanExtra(key: String, def: Boolean = false) = object : ReadWriteProperty<Fragment, Boolean>
{
    private var cacheValue: Boolean? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Boolean
    {
        if (activity != null && cacheValue == null)
        {
            cacheValue = activity!!.intent.getBooleanExtra(key, def)
            if (cacheValue == def)
            {
                val s = activity!!.intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.boolean
                }
            }
        }
        return cacheValue ?: def
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Boolean)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value)
    }
}

fun Fragment.intentDoubleExtra(key: String, def: Double = 0.0) = object : ReadWriteProperty<Fragment, Double>
{
    private var cacheValue: Double? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Double
    {
        if (activity != null && cacheValue == null)
        {
            cacheValue = activity!!.intent.getDoubleExtra(key, def)
            if (cacheValue == def)
            {
                val s = activity!!.intent.getStringExtra(key)
                if (s != null)
                {
                    cacheValue = s.double
                }
            }
        }
        return cacheValue ?: 0.0
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Double)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value)
    }
}

fun Fragment.intentJsonExtra(key: String) = object : ReadWriteProperty<Fragment, JSONObject>
{
    private var cacheValue: JSONObject? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): JSONObject
    {
        if (activity != null && cacheValue == null)
        {
            val extra = activity!!.intent.getStringExtra(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = JSONObject(extra)
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue ?: JSONObject()
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: JSONObject)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value.toString())
    }
}

fun Fragment.intentJsonArrayExtra(key: String) = object : ReadWriteProperty<Fragment, JSONArray>
{
    private var cacheValue: JSONArray? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): JSONArray
    {
        if (activity != null && cacheValue == null)
        {
            val extra = activity!!.intent.getStringExtra(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = JSONArray(extra)
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue ?: JSONArray()
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: JSONArray)
    {
        cacheValue = value
        activity?.intent?.putExtra(key, value.toString())
    }
}

/********************************************************** frag args ****************************************************/

fun Fragment.argIntExtra(key: String, def: Int = 0) = object : ReadWriteProperty<Fragment, Int>
{
    private var cacheValue: Int? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Int
    {
        if (arguments != null && cacheValue == null)
        {
            cacheValue = arguments!!.getInt(key, def)
            if (cacheValue == def)
            {
                val s = arguments!!.getString(key)
                if (s != null)
                {
                    cacheValue = s.int
                }
            }
        }
        return cacheValue ?: def
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Int)
    {
        cacheValue = value
        arguments?.putInt(key, value)
    }
}

fun Fragment.argStringExtra(key: String, def: String = "") = object : ReadWriteProperty<Fragment, String>
{
    private var cacheValue: String? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): String
    {
        if (arguments != null && cacheValue == null)
        {
            cacheValue = arguments!!.getString(key, def)
        }
        return cacheValue ?: def
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: String)
    {
        cacheValue = value
        arguments?.putString(key, value)
    }
}

fun Fragment.argLongExtra(key: String, def: Long = 0) = object : ReadWriteProperty<Fragment, Long>
{
    private var cacheValue: Long? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Long
    {
        if (arguments != null && cacheValue == null)
        {
            cacheValue = arguments!!.getLong(key, def)
            if (cacheValue == def)
            {
                val s = arguments!!.getString(key)
                if (s != null)
                {
                    cacheValue = s.long
                }
            }
        }
        return cacheValue!!
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Long)
    {
        cacheValue = value
        arguments?.putLong(key, value)
    }
}

fun Fragment.argBooleanExtra(key: String, def: Boolean = false) = object : ReadWriteProperty<Fragment, Boolean>
{
    private var cacheValue: Boolean? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Boolean
    {
        if (arguments != null && cacheValue == null)
        {
            cacheValue = arguments!!.getBoolean(key, def)
            if (cacheValue == def)
            {
                val s = arguments!!.getString(key)
                if (s != null)
                {
                    cacheValue = s.boolean
                }
            }
        }
        return cacheValue ?: def
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Boolean)
    {
        cacheValue = value
        arguments?.putBoolean(key, value)
    }
}

fun Fragment.argDoubleExtra(key: String, def: Double = 0.0) = object : ReadWriteProperty<Fragment, Double>
{
    private var cacheValue: Double? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Double
    {
        if (arguments != null && cacheValue == null)
        {
            cacheValue = arguments!!.getDouble(key, def)
            if (cacheValue == def)
            {
                val s = arguments!!.getString(key)
                if (s != null)
                {
                    cacheValue = s.double
                }
            }
        }
        return cacheValue ?: 0.0
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Double)
    {
        cacheValue = value
        arguments?.putDouble(key, value)
    }
}

fun Fragment.argJsonExtra(key: String) = object : ReadWriteProperty<Fragment, JSONObject>
{
    private var cacheValue: JSONObject? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): JSONObject
    {
        if (arguments != null && cacheValue == null)
        {
            val extra = arguments!!.getString(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = JSONObject(extra)
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue ?: JSONObject()
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: JSONObject)
    {
        cacheValue = value
        arguments?.putString(key, value.toString())
    }
}

fun Fragment.argJsonArrayExtra(key: String) = object : ReadWriteProperty<Fragment, JSONArray>
{
    private var cacheValue: JSONArray? = null

    override fun getValue(thisRef: Fragment, property: KProperty<*>): JSONArray
    {
        if (arguments != null && cacheValue == null)
        {
            val extra = arguments!!.getString(key)
            if (extra != null)
            {
                try
                {
                    cacheValue = JSONArray(extra)
                } catch (e: Exception)
                {
                }
            }
        }
        return cacheValue ?: JSONArray()
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: JSONArray)
    {
        cacheValue = value
        arguments?.putString(key, value.toString())
    }
}